package network

import (
	"net"
	"github.com/wanhuo/GoSocketFrame/common"
	"sync"
	"github.com/wanhuo/GoSocketFrame/protocol"
	"errors"
	"bytes"
	"encoding/gob"
	"log"
	"time"
)

type StopWrite struct{}

type SocketConnector struct {
	conn             net.Conn                   //连接
	autoReconnectSec int                        //重连间隔时间, 0为不重连
	closeSignal      chan bool                  //关闭信号
	iattemper        common.IAttemperEngineSink //上层调度
	stream           protocol.PacketStream      //流
	useritem         interface{}                //绑定的用户数据
	writeChan        chan interface{}           //写入通道
	iskeep           bool                       //是否保持长连接
	ip               string                     //连接的地址
	endSync          sync.WaitGroup             //同步锁
	isdone           bool                       //标志是否断开
}

func (self *SocketConnector) Start(ip string) error {
	self.ip = ip
	return self.connect()
}

func (self *SocketConnector) Stop() bool {
	if !self.isdone {
		self.isdone = true
		self.writeChan <- StopWrite{}
	}
	return true
}

func (self *SocketConnector) connect() error {
	tcpAddr, err := net.ResolveTCPAddr("tcp", self.ip)
	if err != nil {
		return err
	}

	self.conn, err = net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return err
	}

	//和中心服务器通讯不需要加密
	self.stream = protocol.NewPacketStream(self.conn)

	// 退出线程
	go self.existThread()

	// 接收线程
	go self.recvThread()

	// 发送线程
	go self.sendThread()

	self.isdone = false

	self.iattemper.OnEventTCPSocketLink(self)

	return nil
}

//发包
func (self *SocketConnector) Send(mainId uint16, subId uint16, data []byte) error {
	pkt := protocol.MakePacket(mainId, subId, data)

	if self.isdone {
		return errors.New("connector has done!")
	} else {
		self.writeChan <- pkt
	}

	return nil
}

func (self *SocketConnector) SendGobMessage(mainId uint16, subId uint16, e interface{}) error {
	var netdata bytes.Buffer
	enc := gob.NewEncoder(&netdata)
	if err := enc.Encode(e); err != nil {
		log.Println("SendGobMessage Encode(", e, "):", err)
		return err
	}
	return self.Send(mainId, subId, netdata.Bytes())
}

func (self *SocketConnector) sendThread() {
	for {
		switch pkt := (<-self.writeChan).(type) {
		// 封包
		case *protocol.Packet:
			if err := self.stream.Write(pkt); err != nil {
				goto exist_loop
			}
		case *StopWrite:
			goto exist_loop
		}
	}

exist_loop:
// 关闭socket,触发读错误, 结束读循环
	self.stream.Close()
	self.endSync.Done()
}

func (self *SocketConnector) recvThread() {
	for {
		//从Socket读取封包
		pk, err := self.stream.Read()
		if err != nil {
			break
		}

		ret := self.iattemper.OnEventTCPSocketRead(pk.MainId, pk.SubId, pk.Data, self)
		if false == ret {
			break
		}
	}

	//通知关闭写协程
	if !self.isdone {
		self.writeChan <- &StopWrite{}
	}
	self.endSync.Done()
}

func (self *SocketConnector) existThread() {
	self.endSync.Add(2)
	self.endSync.Wait()

	self.iattemper.OnEventTCPSocketShut(self)

	if self.iskeep {
		for {
			err := self.connect()
			if err == nil {
				break
			}
			time.Sleep(30 * time.Second)
		}
	}
}

func NewConnector(attemper common.IAttemperEngineSink) *SocketConnector {
	self := &SocketConnector{
		iattemper: attemper,
		writeChan: make(chan interface{}),
		isdone:    true,
		iskeep:    true,
	}

	return self
}
